开发过程中少不了踩坑,记录下各个踩坑的详情,给自己带来便利的同时,也能给其他人提供或多或少的帮助,这就再好不过了。第一期有两个问题,分别是 Bootstrap 表格中插入按钮导致表格自适应失效 ,以及 axios.js 在 Vue.js 的搭配使用过程中的 this 无法指向 Vue 对象

问题1 : Bootstrap 表格中插入按钮导致表格自适应失效

问题描述:

昨天在写前台的时候,把前台的表格使用了Bootstrap美化了一下,立刻漂亮了很多,然后随手将表格里面的两个 a 标签加上了btn btn-danger btn-smbtn btn-success btn-sm 两个类,效果增强了很多,如图:

image
image

今天在写前台代码的时候,突然发现表格中的文字的行距不再居中对齐了,文本位置偏上。

image
image

思考过程:

  1. 应该不是什么太大的问题吧,去问下前端比较厉害的同学吧,发了信息,该过年了比较忙,没有来得及回复。
  2. 直接去调整表格里面文字的 lin-hight 吧,直接去浏览器定位到单元格的类,然后回编辑器进行修改。

解决问题的思路:

想如果适应到其他设备上,写固定值的行高会不会不合适?但是好像又没有什么好的解决方案,但是灵光一动想到(吃饱了以后想到),a 标签是行内元素,button 是块级元素,给 a 标签添加上 btn 类的时候,是否将 a 标签由行内元素转换成块级元素?实验后发现,想法正确。不添加 btn 类只是单独的 a 标签,这个时候表格的自适应还是有效的;将 a 标签换成 button 标签后,表单的自适应失效。

image
image

既然发现了问题所在,那就容易解决了,将添加过 btn btn-danger btn-sm 的 a 标签由块级元素重新转换成行内元素就行了。

考虑到其他地方添加 btn 类的内容不需要转换成行内元素,因此这里解决的办法是在内联样式表中添加上这样一行,或者是写一个类,只有下面一条样式,然后将这个类放在 class 属性的最后面。

1
2
3
4
5
6
7
8
9
10
.btn-sm{
display:inline;
}

OR

.ainline{
display:inline;
}
<a class="btn btn-success btn-sm ainline" v-on:click="">另一种方法</a>

如果你有更好的解决方案,请一起沟通。

发现问题产生原因所在,和解决问题一样重要。

问题2:axios.js 在 Vue.js 的配合中的 this

以前在使用 Vue 向后台发送 ajax 请求的时候,使用的是 vue-resource.js ,不过现在 Vue 已经停止更新 vue-resource ,转而建议使用 axios.js ,新手注定多踩坑。

问题描述:

在 vue-resource 向后台发送 ajax 的时候,只需要简单的一行 js 代码就能搞定,当然 axios.js 也是很简单的一行就能搞定,但是问题出在了接收数据的环节。下面请看 vue-resource 的解决方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
var user = new Vue({
el: "#app",
data: {
userListApiUrl: '/Home/UserList',
jsondata: []
},
methods: {
getRequest: function () {
this.$http.get(this.userListApiUrl).then(function (res) {
this.jsondata = res.body;
})
}
})

其中,在 then(function (res){} 函数中,直接就能把从后台返回的数据赋值给 this.jsondata ,很简洁也很简单。

但是 axios 按照这个格式去写的话,也能拿到后台返回的数据,但是就是不能将返回的数据 赋值给 this.jsondata

(axios 的语法不再前面添加 this)

1
2
3
4
5
6
7
8
9
10
11
12
13
var user = new Vue({
el: "#app",
data: {
userListApiUrl: '/Home/UserList',
jsondata: []
},
methods: {
getRequest: function () {
axios.get(this.userListApiUrl).then(function (res) {
this.jsondata = res.data;
})
}
})

思考过程:

出现这样的问题一直百思不得其解,难不成只能一直使用 vue-resource ? 向困难低头不是我的作风。羊毛出在羊身上,从浏览器上寻找问题。

通过对 js 代码打断点发现了一个现象:

image
image

这个 this 好像指向了 Window 对象,回头查看两段代码,发现了区别:

1
2
3
4
5
6
7
8
// vue-resource
this.$http.get(this.userListApiUrl).then(function (res) {
this.jsondata = res.body;
})
// axios
axios.get(this.userListApiUrl).then(function (res) {
this.jsondata = res.data;
})

vue-resource 在使用前加了 this,根据代码所在的位置,可以判断出第一个和第二个 this 指向的对象都是 user 这个 Vue 对象,因此该段代码的作用域还是在new Vue() 中,这样的话里面的第三个 this 指向的也是 user 对象。

同时, vue-resource 能在前面添加 this 说明 vue-resource 集成在了 Vue 框架中,因此需要添加 this. 才能正常使用,但是在 axios 有没有集成到 Vue 框架中我并不知道啊(事后实验发现在 Vue 中通过 this 并不能访问到 axios 也可能是我的操作不对),官方的Demo就直接这样写了也没见加 this,因此在 axios 代码段中,第一个 this 因为作用域的原因,指向的是 user 这个 Vue 对象,但是里面的 this 因为没有集成到 Vue 同时 axios.js 是独立的 js 文件,作用域为顶级作用域,因此第二个 this 指向的是 Window 这个对象。

解决过程:

既然发现问题出在哪里了,那就比较容易解决了,既然 axios 内部的作用域是顶级作用域,那么 user 对象就和其处在同一个作用域中了,修改后的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
var user = new Vue({
el: "#app",
data: {
userListApiUrl: '/Home/UserList',
jsondata: []
},
methods: {
getRequest: function () {
axios.get(this.userListApiUrl).then(function (res) {
user.jsondata = res.data;
})
}
})

同时,根据 Vue 的生命周期钩子函数的执行顺序,在此位置访问 user 应该是没有问题的。

问题解决。

如果你有其他的看法,一起交流。

多看,多实践。